home *** CD-ROM | disk | FTP | other *** search
-
- /***************************************************************************
-
- V_M_6502.C - A virtual machine emulator
-
- (c) 1986 Darek Mihocka
-
- People I'd like to thank before they sue me:
- - Ignac Kolenko for helping me code and debug this program.
- - Megamax Inc. for making code a joy to write.
- - everyone else in Toronto who encouraged me to write this program.
-
- Microprocessor : 6502 @ 250kHz
- Hardware : 48K Apple ][
- Operating system: none, but one can be loaded from disk
-
- Last update: December 31, 1986
-
- ***************************************************************************/
-
- #include <stdio.h>
- #include <osbind.h>
-
- #define LOOP while(1)
- #define print(x) put_line(x)
- #define put(x) outchar(x)
- #define CR print("\n\r")
- #define BEL '\007'
- #define CLS print("\033E")
-
- static char *hex= {"0123456789ABCDEF"} ;
-
- char buf[80] , /* monitor line input buffer */
- ch , /* character at buf[tp] */
- asc[17] , /* buffer for ASCII dump */
- hardcopy, /* if non-zero dumps to printer */
- *mem, /* 65536 bytes to simulate 6502 memory */
- *stat, /* status bits for each byte */
- *scr, /* pointer to start of screen */
- *scr_emul ; /* pointer to start of emulation screen */
-
- int len, /* length of inputted line */
- tp , /* pointer to current character in buf[] */
- MAXCOL ,
- MAXROW ,
- MAXBYTE ,
- hand, /* disk handle */
- mode ; /* screen resolution */
-
- int cpu ; /* type of cpu to emulate */
- unsigned int pc , /* program counter (16 bits) */
- ea ;
- unsigned char a,x,y,sp,ir, p, trace ;
-
- struct DTA { /* for disk directories */
- char reserved[21] ;
- char attrib ;
- int time, date ;
- long size ;
- char fname[11] ;
- } ioblock ;
-
- struct disk_info {
- long b_free,b_total,b_sec_siz,b_cl_siz ; } diskblock ;
-
- #include "V_M_HDWR.INC"
- #include "V_M_OPS.INC"
-
- /*********************************************************************/
-
- help () {
-
- CR ;
- print(" *** ST TRANSFORMER DEMO ***\n\r") ;
- CR ; CR ;
- print(" Syntax: ( all numbers are in hex )\n\r") ;
- CR ;
- print(" ssss - starting address\n\r") ;
- print(" eeee - ending address\n\r") ;
- print(" dddd - destination address\n\r") ;
- print(" nn - an 8 bit value\n\r") ;
- CR ;
- print(" Command Summary:\n\r") ;
- CR ;
- print(" : ssss nn [nn [nn [nn ...]]] - ") ;
- print("change contents of memory starting from ssss\n\r") ;
- print(" B - ") ;
- print("boot up the virtual computer\n\r") ;
- print(" D ssss [eeee] - ") ;
- print("display memory from ssss to eeee or one line\n\r") ;
- print(" G ssss - ") ;
- print("start emulating at ssss \n\r") ;
- print(" H nn - ") ;
- print("nn is non-zero for hardcopy \n\r") ;
- print(" I - ") ;
- print("index of binary files on the disk\n\r") ;
- print(" L ssss [eeee] - ") ;
- print("disassemble from ssss to eeee or one page\n\r") ;
- print(" M ssss eeee dddd - ") ;
- print("move memory block from ssss to dddd\n\r") ;
- print(" R file - ") ;
- print("read memory block \n\r") ;
- print(" S [ssss] - ") ;
- print("single step at aaaa or program counter\n\r") ;
- print(" T [ssss] - ") ;
- print("trace at aaaa or program counter\n\r") ;
- print(" V - ") ;
- print("view emulated screen display \n\r") ;
- print(" W ssss eeee file - ") ;
- print("save memory block from ssss to dddd\n\r") ;
- print(" X - ") ;
- print("exit this great program\n\r") ;
- CR ; CR ;
-
- }
-
- outchar(x) char x ; {
-
- Bconout (2,x) ; /* print to screen */
- if ((hardcopy)&&(Bconstat(0)))
- Bconout (0,x) ; /* print to printer */
- }
-
- put_line(lin)
- char *lin ; { /* write string to screen */
-
- char c ;
- while (c=*lin++) put (c) ;
- }
-
-
- get_line(maxc) int maxc ; { /* get line in buf[], set tp and len */
-
- long key ; /* scan code and character code returned by Bconin */
- len = 0 ; /* initialize input line length to 0 */
-
- LOOP {
- key = Bconin(2) ; /* get a key */
- ch = (char) key ; /* isolate character code */
- if (ch>='a' && ch<='z') ch -= 32 ; /* lowercase becomes uppercase */
- if (ch>=' ' && ch <='_') { /* if it's printable */
- put(ch) ; /* then print it and store it */
- buf[len++] = ch ;
- } /* if Backspace, delete last */
- if (ch==8 && len>0) { /* character and reduce buffer */
- print("\b \b") ;
- len-- ;
- }
- if (len==0 && ch==0) { /* if special key */
- ch = (char) (key>>16) ; /* get scan code */
- if (ch==0x47) CLS ; /* is it Home? */
- if (ch==0x62) help() ; /* is it Help? */
- break ; /* break out of loop */
- }
- /* stay in loop until buffer full or Return pressed */
- if (len==maxc || ch==13 || ch=='\n' || ch == '\033') break ;
- }
- CR ;
- buf[len] = 0 ; /* terminate input line with a null character */
- tp = 0 ; /* text pointer points to first character */
-
- }
-
-
- skip_space () /* advance tp to point to non-space */
- {
- while ((ch=buf[tp])==' ' && tp<len) tp++ ;
- }
-
-
- skip_blank () /* advance tp to point to non-blank */
- {
- while (((ch=buf[tp])<'0' || (ch>'9' && ch<'A') || (ch>'F')) && tp<len) tp++ ;
- }
-
-
- unsigned char get_byte () { /* return 8 bit value at tp */
-
- unsigned char byte=0, digit=0 ;
-
- skip_blank() ;
- while ((tp<len) && ( /* find next hex character */
- ((ch = buf[tp]) >='0' && ch<='9') ||
- (ch>='A' && ch<='F')
- )
- && (digit++<2) ) {
- byte <<= 4 ;
- byte += (ch>='0' && ch<='9') ? ch-48 : ch-55 ;
- tp++ ;
- }
- return (byte) ;
- }
-
-
-
- unsigned int get_addr () { /* return 16 bit value at tp */
-
- unsigned int addr=0, digit=0 ;
-
- skip_blank() ;
- while ( (((ch = buf[tp]) >='0' && ch<='9')
- || (ch>='A' && ch<='F'))
- && (digit++<4) ) {
- addr <<= 4 ;
- addr += (ch>='0' && ch<='9') ? ch-48 : ch-55 ;
- tp++ ;
- }
- return (addr) ;
- }
-
- /* disassemble #line commands starting at current pc */
-
- disasm(line) int line ; {
-
- int bits, modes ;
- unsigned char opcode ;
- long crunch ;
-
- while (line--) {
- showpc() ;
- opcode = *(mem+pc) ;
- crunch = mnemonics[opcode] ;
-
- modes = crunch&0x0FL ;
-
- showhex(pc) ;
- put(' ') ;
-
- switch (modes) {
-
- case 0x00 :
- case 0x0A : print (" ") ;
- break ;
-
- case 0x01 :
- case 0x02 :
- case 0x03 :
- case 0x04 :
- case 0x05 :
- case 0x06 :
- case 0x0B : showhex(pc+1) ;
- print (" ") ;
- break ;
-
- case 0x07 :
- case 0x08 :
- case 0x09 :
- case 0x0C : showhex(pc+1) ;
- put(' ') ;
- showhex(pc+2) ;
- put(' ') ;
- break ;
- }
-
- for (bits=24 ; bits >0 ; bits -=8 ) {
- put((char)(crunch>>24)) ;
- crunch <<= 8 ;
- }
- put (' ') ;
-
- pc++ ;
- switch (modes) {
-
- case 0x00 : print (" ") ;
- break ;
-
- case 0x01 : print (" #$") ;
- showhex(pc++) ;
- print (" ") ;
- break ;
-
- case 0x02 : print(" $") ;
- showhex(pc++) ;
- print (" ") ;
- break ;
-
- case 0x03 : print (" $") ;
- showhex(pc++) ;
- print (",X") ;
- print (" ") ;
- break ;
-
- case 0x04 : print (" $") ;
- showhex (pc++) ;
- print (",Y") ;
- print (" ") ;
- break ;
-
- case 0x05 : print (" ($") ;
- showhex (pc++) ;
- print (",X)") ;
- print (" ") ;
- break ;
-
- case 0x06 : print (" ($") ;
- showhex (pc++) ;
- print ("),Y") ;
- print (" ") ;
- break ;
-
- case 0x07 : print (" $") ;
- showhex (pc+1) ;
- showhex (pc) ;
- print (" ") ;
- pc +=2 ;
- break ;
-
- case 0x08 : print (" $") ;
- showhex (pc+1) ;
- showhex (pc) ;
- pc +=2 ;
- print (",X") ;
- print (" ") ;
- break ;
-
- case 0x09 : print (" $") ;
- showhex (pc+1) ;
- showhex (pc) ;
- pc +=2 ;
- print (",Y") ;
- print (" ") ;
- break ;
-
- case 0x0A : print (" A") ;
- print (" ") ;
- break ;
-
- case 0x0B : print (" $") ;
- showaddr (pc + 1 + (int)((char)(*(mem+pc)))) ;
- print (" ") ;
- pc ++ ;
- break ;
-
- case 0x0C : print (" ($") ;
- showhex(pc+1) ;
- showhex(pc) ;
- put (')') ;
- print (" ") ;
- pc+=2 ;
- break ;
-
- default : break ;
- }
- if (!trace) CR ;
-
- }
- }
-
- showreg() {
-
- print ("PC=") ; showpc() ;
- print ("A=") ; showbyte(a) ;
- print (" X=") ; showbyte(x) ;
- print (" Y=") ; showbyte(y) ;
- print (" S=") ; showbyte(sp) ;
- print (" P=") ; showbyte(p) ;
- print (" ") ;
- (p&NBIT) ? put('N') : put ('.') ;
- (p&VBIT) ? put('V') : put ('.') ;
- (p&BBIT) ? put('B') : put ('.') ;
- (p&DBIT) ? put('D') : put ('.') ;
- (p&IBIT) ? put('I') : put ('.') ;
- (p&ZBIT) ? put('Z') : put ('.') ;
- (p&CBIT) ? put('C') : put ('.') ;
- put (' ') ;
- }
-
-
- /* routine to single step, trace, or execute at current pc */
-
- emulate (count, mode) int count, mode ; {
-
- unsigned int pctemp ;
- unsigned char ptemp ;
- long usp, start_time, end_time ;
-
- switch (mode) {
-
- case 0 : /* regular emulation */
-
- usp = Super(0L) ; /* must go to supervisor mode */
- show_emul() ;
- execute() ;
- show_scr() ;
- Super(usp) ;
- showreg() ;
- if (trace) print ("EA: ") ;
- showaddr (ea) ;
- CR ;
- trace=0 ;
- break ;
-
- case 1 : /* single step mode */
- pctemp = pc ; /* remember pc */
- disasm(1) ; /* dissassemble current opcode */
- pc = pctemp ; /* restore pc */
- trace=255 ;
- emulate(0,0) ;
- break ;
-
- case 2 : /* trace mode */
- p &= ~BBIT ;
- while (count-- && !(p&BBIT)) emulate(0,1) ;
- break ;
-
- }
- }
-
- mon() { /* the 6502 monitor */
-
- int quit=0 ; /* quit flag */
- char com ; /* command character */
- int digit, chptr, cntr ; /* temporary variables */
- unsigned addr1, addr2, addr3, byt ;
- unsigned char header[6] ;
-
- do {
- print ("\n\r>") ; /* print prompt */
- get_line(MAXCOL) ; /* get a line of input */
- skip_space() ; /* skip any leading spaces */
- com = buf[tp++] ; /* get command character */
-
- if (com!='R') addr1 = get_addr() ; /* no numbers for R */
-
- switch(com) {
-
- case '\000' : /* empty line or comment is ignored */
- case ';' : break ;
-
- case 'X' : quit++ ; /* X to quit */
- break ;
-
- case 'M' : pc = addr1 ; /* block memory move */
- addr2 = get_addr() ;
- addr3 = get_addr() ;
- while (addr1<=addr2) *(mem+addr3++) = *(mem+addr1++) ;
- break ;
-
- case ':' : pc = addr1 ; /* modify memory */
- skip_blank() ;
- while (buf[tp] && (tp<len)) {
- *(mem+pc++) = get_byte() ;
- skip_blank() ;
- }
- break ;
-
- case 'D' : pc = addr1 ; /* dump memory */
- addr2 = get_addr() ;
- if (addr2 <= addr1) addr2 = addr1 + MAXBYTE - 1 ;
- do {
- showpc() ;
- for (cntr=0; cntr<MAXBYTE; cntr++) {
- if (pc<=addr2) {
- ch = (*(mem+pc))&0x7F ;
- asc[cntr] = (ch>=32 && ch<=127) ? ch : '.' ;
- showhex(pc++) ;
- put (' ');
- }
- else {
- asc[cntr] = ' ' ;
- print (" ") ;
- }
- }
- for (cntr=0; cntr<MAXBYTE; cntr++) put(asc[cntr]) ;
- CR ;
- } while (pc<=addr2 && pc>0x000F) ;
- break ;
-
- case 'L' : if (len>1) pc = addr1 ; /* disassemble memory */
- disasm(MAXROW-4) ;
- break ;
-
- case 'T' : if (len>1) pc = addr1 ; /* trace execution */
- p &= ~BBIT ;
- emulate(35,2) ;
- break ;
-
- case 'B' : pc = (*(mem+0xFFFD)*256)+(*(mem+0xFFFC)) ; /* RESET vector */
- p &= ~BBIT ;
- emulate(0,0) ;
- break ;
-
- case 'G' : pc = addr1 ; /* execute 6502 code */
- p &= ~BBIT ;
- emulate(0,0) ;
- break ;
-
- case 'S' : if (len>1) pc = addr1 ; /* step execution */
- (*emulate)(0,1) ;
- break ;
-
- case '.' : showreg() ; /* dump registers */
- break ;
-
- case 'I' : /* index of binary files, i.e. a directory */
- {
- int file_count=0 ;
- long fre_by ;
- Fsetdta(&ioblock) ;
- if (Fsfirst("*.BIN",0)>=0) {
- print ("Directory of binary files:") ; CR ; CR ;
- print ("filename bytes") ; CR ;
- do {
- file_count++ ;
- for (x=0; (x<8) && (ioblock.fname[x] != '.') ;
- put(ioblock.fname[x++])) ;
- for (;x++<9;put (' ') ) ;
- if ((ioblock.size - 6L) < 65537L)
- printf ("%6ld\n",ioblock.size-6L);
- } while (Fsnext()>=0) ;
- }
- CR ;
- Dfree (&diskblock,0) ;
- fre_by = (diskblock.b_sec_siz * diskblock.b_cl_siz *
- diskblock.b_free) ;
- printf("\n%d file(s) %ld bytes free\n",file_count,fre_by);
- fflush (stdout) ;
- break ;
- }
-
- case 'W' : pc = addr1 ; /* write memory to binary file */
- addr2 = get_addr() ;
- if (addr2 < addr1) break ;
- skip_space() ;
- if (tp==len) break ;
- strncpy (&buf[len],".bin",5) ; /* append to filename */
- if ((hand=Fcreate (&buf[tp],0))<0) break ;
- print ("Writing...") ; CR ;
- header[0] = header[1] = 255 ;
- header[2] = addr1 ; /* lo - hi format */
- header[3] = addr1>>8 ;
- header[4] = addr2 ;
- header[5] = addr2>>8 ;
- if (Fwrite (hand,6L,header)<0) {
- print ("Write error") ; CR ;
- goto err_close ;
- }
- if (Fwrite
- (hand,(long)addr2-(long)addr1+1L,
- mem+addr1)<0) {
- print ("Write error") ; CR ;
- goto err_close ;
- }
- Fclose (hand) ;
- break ;
-
- err_close:
- Fclose (hand) ;
- break ;
-
- case 'R' : skip_space() ; /* read binary file to memory */
- if (tp==len) break ;
- strncpy (&buf[len],".bin",5) ;
- if ((hand = Fopen (&buf[tp],0))<0) goto err_close ;
- print ("Reading... ") ;
- if (Fread (hand,6L,header)<0) {
- print ("File not found") ; CR ;
- goto err_close ;
- }
- if (header[1]&header[0] != 255) /* verify it's binary file */
- {
- print ("Not binary file") ;
- goto err_close ;
- }
- addr1 = header[2] + (header[3] << 8) ;
- addr2 = header[4] + (header[5] << 8) ;
- if (Fread
- (hand,(long)addr2-(long)addr1+1L,
- mem+addr1)<0) {
- print ("EOF reached") ;
- goto err_close ;
- }
- printf ("\nstart %4x end %4x\n",addr1,addr2) ;
- Fclose (hand) ;
- break ;
-
- case 'H' : hardcopy = addr1 ; /* set hardcopy on/off flag */
- break ;
-
- case 'V' : show_emul() ; /* view virtual machine screen */
- getchar() ;
- show_scr() ;
- break ;
-
- default : put(BEL) ; /* otherwise beep */
-
- }
- } while (!quit) ;
- }
-
-
- showpc() { /* print out PC */
-
- int bit ;
-
- for (bit = 12; bit>=0; bit-=4) put (hex[(pc>>bit)&0x0F]) ;
- print(": ") ;
- }
-
-
- showaddr(addr) unsigned int addr ; /* print 16 bit number */
- {
- put (hex[addr>>12]) ;
- put (hex[(addr>>8)&0x0f]) ;
- put (hex[(addr>>4)&0x0f]) ;
- put (hex[addr&0x0f]) ;
- }
-
- showhex(addr) unsigned int addr ; /* print 8 bit number in memory */
- {
- unsigned char byte ;
-
- byte = *(mem+addr) ;
- put (hex[byte>>4]) ;
- put (hex[byte&0x0f]) ;
- }
-
- showbyte(byte) unsigned char byte ; /* print 8 bit number */
- {
- put (hex[byte>>4]) ;
- put (hex[byte&0x0f]) ;
- }
-
-
- col25() { /* switch to 25 row color mode */
- asm { /* code borrowed from HI50.PRG */
- DC.W 0xA000 /* call LINEA to return some pointers */
- MOVE.L 4(A1),A1 /* get pointer to 8x8 font data */
- MOVE.L 72(A1),-0x0A(A0) /* beats me?? */
- MOVE.L 76(A1),-0x16(A0)
- MOVE.W #8,-0x2E(A0) /* character height is 8 */
- MOVE.W #24,-0x2A(A0) /* 25 rows on the screen */
- MOVE.W #1280,-0x28(A0) /* 1280 bytes per screen row */
- }
- }
-
- mon25() { /* switch to 25 row monochrome mode */
- asm {
- DC.W 0xA000
- MOVE.L 8(A1),A1 /* 8x16 font */
- MOVE.L 72(A1),-0x0A(A0)
- MOVE.L 76(A1),-0x16(A0)
- MOVE.W #16,-0x2E(A0) /* character height is 16 */
- MOVE.W #24,-0x2A(A0) /* 25 rows */
- MOVE.W #1280,-0x28(A0) /* etc. etc. left to reader */
- }
- }
-
- mon50() { /* switch to 50 row monochrome mode */
- asm {
- DC.W 0xA000
- MOVE.L 4(A1),A1
- MOVE.L 72(A1),-0x0A(A0)
- MOVE.L 76(A1),-0x16(A0)
- MOVE.W #8,-0x2E(A0)
- MOVE.W #43,-0x2A(A0)
- MOVE.W #720,-0x28(A0)
- }
- }
-
- show_emul() { /* display virtual video chip output */
- Setscreen (scr_emul,scr_emul,-1) ;
- }
-
- show_scr() { /* display 6502 monitor output */
- Setscreen (scr,scr,-1) ;
- }
-
- colors8() {
-
- if (mode==0) {
- Setcolor ( 0,0x0000) ; /* black */
- Setcolor ( 3,0x0070) ; /* green */
- Setcolor ( 4,0x0070) ;
- Setcolor (11,0x0740) ; /* orange */
- Setcolor (12,0x0740) ;
- Setcolor ( 2,0x0405) ; /* violet */
- Setcolor ( 5,0x0405) ;
- Setcolor (10,0x0007) ; /* blue */
- Setcolor (13,0x0007) ;
- Setcolor ( 1,0x0777) ;
- Setcolor ( 8,0x0777) ;
- Setcolor ( 9,0x0777) ;
- Setcolor ( 6,0x0777) ; /* white */
- Setcolor ( 7,0x0777) ;
- Setcolor (14,0x0777) ;
- Setcolor (15,0x0777) ;
- }
- }
-
- colors16() {
-
- if (mode==0) {
- Setcolor ( 0,0x0000) ; /* black */
- Setcolor ( 1,0x0500) ; /* magenta */
- Setcolor ( 2,0x0004) ; /* dark blue */
- Setcolor ( 3,0x0405) ; /* violet */
- Setcolor ( 4,0x0030) ; /* dark green */
- Setcolor ( 5,0x0444) ; /* grey */
- Setcolor ( 6,0x0007) ; /* blue */
- Setcolor ( 7,0x0457) ; /* light blue */
- Setcolor ( 8,0x0530) ; /* brown */
- Setcolor ( 9,0x0740) ; /* orange */
- Setcolor (10,0x0222) ; /* grey2 */
- Setcolor (11,0x0745) ; /* pink */
- Setcolor (12,0x0070) ; /* bright green */
- Setcolor (13,0x0770) ; /* yellow */
- Setcolor (14,0x0055) ; /* aqua */
- Setcolor (15,0x0777) ; /* white */
- }
- }
-
- /***************************************************************************/
-
- main() {
-
- appl_init() ;
-
- scr = (char *) Physbase() ; /* find screen memory pointer */
- scr_emul = scr - 32768L ;
- mem = scr - 32768L - 65536L; /* must be on a 64K boundary!!!! */
- stat = mem - 65536L + 32768L ; /* use relative addressing */
-
- hardcopy = 0 ; /* hardcopy off */
- put(BEL) ; /* beep to announce our arrival */
-
- mode = Getrez() ; /* get current screen resolution */
- switch (mode) {
- case 0 : col25() ;
- MAXCOL = 38 ; /* set variables used by dumping routine */
- MAXROW = 24 ;
- MAXBYTE = 8 ;
- break ;
-
- case 1 : col25() ;
- MAXCOL = 78 ;
- MAXROW = 24 ;
- MAXBYTE = 16 ;
- break ;
-
- case 2 : mon50() ;
- MAXCOL = 78 ;
- MAXROW = 44 ;
- MAXBYTE = 16 ;
- break ;
- }
-
- print ("\033v") ; /* turn text wraparound on just in case */
-
- print ("Atari ST\277 ST Transformer Demo" ) ; CR ;
- print ("\275 1986,87 Darek Mihocka") ; CR ;
- print ("MegaBaud ST BBS (416)243-9519") ;
- CR ;
- print ("Applesoft and Integer Basic (c) Apple") ; CR ;
- print ("This program is meant to be a demo and") ; CR ;
- print ("not to harm Apple in any way.") ; CR ;
- CR ;
- print ("Release version A2.04 on Dec. 31, 1986") ; CR ;
- print ("Microprocessor : 6502 @ 250kHz") ; CR ;
- print ("Hardware : 48K Apple ][") ; CR ;
- print ("Operating system: none") ; CR ;
- CR ;
- print ("Coming in mid-1987: The ST Transformer") ; CR ;
- print ("Runs Apple, Atari 800, and Commodore 64") ; CR ;
- print ("software all on the ST.") ; CR ;
- CR ;
-
- InitMachine() ; /* initialize virtual machine memory, pointers, etc. */
-
- mon() ; /* go into monitor */
-
- if (mode == 2) mon25(); /* restore 25 row mode */
- else col25() ;
-
- appl_exit() ;
- }
-
-